import { colorMix, hexToRgb } from '@/utils/theme'
export class CanvasAnimate {
  j
  k
  l
  canvas
  tabWidthList
  tabHeight
  opt
  tabs
  pattern
  primaryColor
  primaryRgbColor
  highLightColor
  shadowRgbColor
  systemConfig
  constructor(t, a, e, systemConfig) {
    this.j = 0.85
    this.k = 10
    this.l = 4
    this.canvas = null
    this.tabs = []
    this.pattern = null
    this.tabWidthList = []
    this.tabHeight = 0
    this.primaryColor = ''
    this.primaryRgbColor = ''
    this.highLightColor = ''
    this.shadowRgbColor = ''
    this.systemConfig = systemConfig
    this.opt = {
      currentIndex: 0,
      nextIndex: 1,
      speed: 1,
      timer: 0,
      width: 200,
      height: 100,
      animating: !1,
      curDisX: 0,
      distance: 0
    }
    this.canvas = document.getElementById(t)
    this.tabs = document.querySelectorAll(a)
    this.calcTabs()
    this.initCanvas(this.canvas, this.opt.width, this.opt.height)
    this.createPattern(this.canvas)
    this.startDraw(0)
    this.toggle(e)
  }
  initCanvas(t, a, e) {
    const i = t.getContext('2d')
    const { devicePixelRatio: s } = window
    t.width = a * s
    t.height = e * s
    t.style.width = `${a}px`
    t.style.height = `${e}px`
    i.scale(s, s)
    this.primaryColor = getComputedStyle(document.querySelector('html')).getPropertyValue('--el-color-primary')
    this.primaryRgbColor = getComputedStyle(document.querySelector('html')).getPropertyValue('--el-color-primary-rgb')
    this.highLightColor = colorMix(this.systemConfig.isLight ? '#000000' : '#ffffff', this.primaryColor, this.systemConfig.isLight ? 0.7 : 0.3)
    this.shadowRgbColor = hexToRgb(colorMix(this.systemConfig.isLight ? '#ffffff' : '#000000', this.primaryColor, 0.5))
  }
  calcTabs() {
    const e = []
    let i = 0
    this.tabs.forEach((t, idx) => {
      e.push(t.offsetLeft)
      if (idx === this.tabs.length - 1) {
        i += t.offsetLeft
        i += t.offsetWidth
      }
    })
    e.push(i)
    this.tabWidthList = e
    this.tabHeight = this.tabs[0].offsetHeight
    this.opt.height = this.tabHeight + 8
    this.opt.width = window.innerWidth
  }
  createPattern(t) {
    const a = document.createElement('canvas')
    a.width = 140
    a.height = 68
    a.style.width = '140px'
    a.style.height = '68px'
    const e = a.getContext('2d')
    e.scale(1, 1)
    e.lineWidth = 0.4
    for (let i = 3, s = 0.8, n = 1; n < 50; n++) {
      e.strokeStyle = `RGBA(${this.primaryRgbColor}, ${s})`
      e.beginPath()
      e.moveTo(0, n * i)
      e.lineTo(140, n * i)
      e.stroke()
      e.closePath()
      n > 10 && (s -= 0.1)
    }
    this.pattern = t.getContext('2d').createPattern(a, 'repeat-x')
  }
  calcAVGSpeed(t) {
    let s = (this.l * this.j * t + this.k * (1 - this.j) * t) / (this.k * this.l * 20)
    s = Math.max(Math.abs(s), 2.5) * Math.sign(s)
    return s
  }
  getCurSpeed(t, a) {
    return Math.abs(t) > Math.abs(this.j * a) ? this.l * this.opt.speed : this.k * this.opt.speed
  }
  calCurve(t, a, e, i, s, n) {
    t.bezierCurveTo(a + n, e, i - n, s, i, s)
  }
  drawHighLight(t) {
    const e = this.canvas.getContext('2d')
    e.clearRect(0, 0, 2 * this.opt.width, 2 * this.opt.height)
    e.shadowColor = `rgba(${this.shadowRgbColor}, 1)`
    e.shadowBlur = 5
    e.strokeStyle = this.primaryColor
    e.lineWidth = 0.8
    e.fillStyle = 'none'
    this.draw(e, !1)
    const i = e.createLinearGradient(0, 0, this.opt.width, this.opt.height)
    const s = t - 0.3
    i.addColorStop(Math.min(1, Math.max(0, 0 + s)), this.systemConfig.isLight ? 'rgba(255,255,255,0)' : 'rgba(0,0,0,0)')
    i.addColorStop(Math.min(1, Math.max(0, 0 + s + 0.1)), this.highLightColor)
    i.addColorStop(Math.min(1, 0 + s + 0.3), this.highLightColor)
    i.addColorStop(Math.min(1, 0 + s + 0.3 + 0.1), this.systemConfig.isLight ? 'rgba(255,255,255,0)' : 'rgba(0,0,0,0)')
    i.addColorStop(1, this.systemConfig.isLight ? 'rgba(255,255,255,0)' : 'rgba(0,0,0,0)')
    e.lineWidth = 2.5
    e.strokeStyle = i
    e.fillStyle = this.pattern
    this.draw(e, !0)
  }
  startDraw(t) {
    this.drawHighLight(t)
    this.opt.timer = requestAnimationFrame(() => {
      this.startDraw((t + 0.005) % 1.6)
    })
  }
  draw(t, a) {
    const n = this.opt.currentIndex
    const c = this.tabHeight
    const r = 0.5
    let o = 0
    t.beginPath()
    t.moveTo(-50, this.opt.height + 10)
    t.lineTo(-50, c + r)
    if (this.opt.animating) {
      const t = this.getCurSpeed(this.opt.curDisX, this.opt.distance)
      o = Math.min(Math.abs(this.opt.distance), Math.abs(this.opt.curDisX + t)) * Math.sign(t)
    }
    t.lineTo(0 + this.tabWidthList[n] + o - 20, c + r)
    this.calCurve(t, 0 + this.tabWidthList[n] + o - 20, c + r, 0 + this.tabWidthList[n] + o + 20, 3, 20)
    if (this.opt.animating) {
      const a = this.tabWidthList[this.opt.nextIndex + 1] - this.tabWidthList[this.opt.nextIndex]
      t.lineTo(0 + this.tabWidthList[n] + a + o - 20, 3)
      this.calCurve(t, 0 + this.tabWidthList[n] + a + o - 20, 3, 0 + this.tabWidthList[n] + a + o + 20, c + r, 20)
    } else {
      t.lineTo(0 + this.tabWidthList[n + 1] + o - 20, 3)
      this.calCurve(t, 0 + this.tabWidthList[n + 1] + o - 20, 3, 0 + this.tabWidthList[n + 1] + o + 20, c + r, 20)
    }
    t.lineTo(this.opt.width + 10, c + r)
    t.lineTo(this.opt.width + 10, this.opt.height + 10)
    t.closePath()
    t.stroke()
    a && t.fill()
    a && this.opt.animating && ((this.opt.curDisX = o), Math.abs(o) >= Math.abs(this.opt.distance) && ((this.opt.animating = !1), (this.opt.currentIndex = this.opt.nextIndex)))
  }
  toggle(t) {
    t === this.opt.currentIndex ||
      !this.tabWidthList ||
      !this.tabWidthList.length ||
      (this.opt.animating && t === this.opt.nextIndex) ||
      ((this.opt.animating = !0), (this.opt.distance = this.tabWidthList[t] - this.tabWidthList[this.opt.currentIndex]), (this.opt.speed = this.calcAVGSpeed(this.opt.distance)), (this.opt.curDisX = 0), (this.opt.nextIndex = t))
  }
  resize() {
    this.opt.timer && cancelAnimationFrame(this.opt.timer)
    this.calcTabs()
    this.initCanvas(this.canvas, this.opt.width, this.opt.height)
    this.startDraw(0)
  }
}
